package fr.upstlse.glre.server.util;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.LinkedList;
import java.util.List;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.format.CellFormat;
import jxl.format.Colour;
import jxl.format.Font;
import jxl.format.RGB;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 * Read and write the Workbook into HTML format.
 * <code>
 * 	<div id="emploiDuTempsTableau">
 * 		<table>
 * 		</table>
 * 	</div>
 * </code>
 * @author michael
 *
 */
public class XlsReader {

	static Logger LOGGER = Logger.getLogger(XlsReader.class);

	/**
	 * The output stream to write to
	 */
	private Writer writer;

	/**
	 * The workbook we are reading from
	 */
	private Workbook workbook;

	/**
	 * Constructor
	 * 
	 * @param pWorkbook
	 *            The workbook to interrogate
	 * @param out
	 *            The output stream to which the HTML values are written
	 * @exception java.io.IOException
	 */
	public XlsReader(Workbook pWorkbook, Writer pWriter) throws IOException {
		workbook = pWorkbook;
		writer = pWriter;
	}

	/**
	 * Writes out the workbook data as HTML table, with formatting information
	 */
	public void read() throws IOException {

		BufferedWriter bw = new BufferedWriter(writer);

		bw.write("<div id=\"emploiDuTempsTableau\"");
		bw.write("<table>");
		bw.newLine();
		Sheet lSheet = workbook.getSheet(0);

		List<Integer> lSemaines = getSemainesRowNumber(lSheet);
		for (Integer lRowNumber : lSemaines) {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("Row number = " + lRowNumber);
			}
			String lSemaine = lSheet.getCell(0, lRowNumber).getContents();
			bw
					.write("<tr><td colspan=\"5\" style=\"text-align:center\">Semaine "
							+ lSemaine + "<td></tr>");
			bw.newLine();

			String lJour = lSheet.getCell(1, lRowNumber).getContents();
			bw.write("<tr><td>" + lJour + "</td></tr>");
			getJour(bw, lSheet, lRowNumber);
			getJour(bw, lSheet, lRowNumber + 1);
			lJour = lSheet.getCell(1, lRowNumber + 2).getContents();
			bw.write("<tr><td>" + lJour + "</td></tr>");
			getJour(bw, lSheet, lRowNumber + 2);
			getJour(bw, lSheet, lRowNumber + 3);

		}
		bw.write("</table>");
		bw.newLine();
		bw.write("</div>");
		bw.newLine();

		bw.flush();
		bw.close();
	}

	/**
	 * Writes out the workbook data for the given week as HTML table, with
	 * formatting information
	 * 
	 * @param lSemaine
	 * @throws IOException
	 */
	public void read(String lSemaine) throws IOException {

		BufferedWriter bw = new BufferedWriter(writer);

		bw.write("<div id=\"emploiDuTempsTableau\"");
		bw.write("<table>");
		bw.newLine();
		Sheet lSheet = workbook.getSheet(0);

		bw.write("<th  class=\"sheetTitle\">Semaine " + lSemaine + "</th>");
		bw.newLine();

		Cell lSemaineCell = lSheet.findCell(lSemaine);
		if (lSemaineCell != null) {
			getJour(bw, lSheet, lSemaineCell.getRow());
			getJour(bw, lSheet, lSemaineCell.getRow() + 1);
			getJour(bw, lSheet, lSemaineCell.getRow() + 2);
			getJour(bw, lSheet, lSemaineCell.getRow() + 3);
		}

		bw.write("  </div>");
		bw.newLine();

		bw.write("</table>");
		bw.newLine();
		bw.write("</div>");
		bw.newLine();

		bw.flush();
		bw.close();
	}

	/**
	 * Get and write the day according to the Sheet.
	 * 
	 * @param pBufferedWriter
	 *            Output in which the row is written.
	 * @param pSheet
	 *            Sheet to read
	 * @param pJour
	 *            Day to get.
	 * @throws IOException
	 */
	private void getJour(BufferedWriter pBufferedWriter, Sheet pSheet, int pJour)
			throws IOException {
		pBufferedWriter.write("    <tr class=\"jour\">");
		pBufferedWriter.newLine();
		for (Cell lCell : pSheet.getRow(pJour)) {
			if ((lCell.getColumn() > 1) && (lCell.getColumn() < 7)) {
				CellFormat lCellFormat = lCell.getCellFormat();
				pBufferedWriter.write("      <td");
				if (lCellFormat != null) {
					Colour lColour = lCellFormat.getBackgroundColour();
					RGB lRgb = lColour.getDefaultRGB();
					String lBackgroundColor = "background-color: rgb("
							+ lRgb.getRed() + "," + lRgb.getGreen() + ","
							+ lRgb.getBlue() + ");";

					Font lFont = lCellFormat.getFont();
					String lFontSize = "font-size: " + lFont.getPointSize()
							+ "pt";
					pBufferedWriter.write(" style=\"" + lBackgroundColor + "; "
							+ lFontSize + "\"");
				}
				pBufferedWriter.write(">");
				pBufferedWriter.newLine();
				String lContent = lCell.getContents();
				byte[] lUtf8Content = lContent.getBytes("UTF-8");
				lContent = new String(lUtf8Content, "UTF-8");
				pBufferedWriter.write(lContent);
				pBufferedWriter.newLine();
				pBufferedWriter.write("      </td>");
				pBufferedWriter.newLine();
			}
		}
		pBufferedWriter.write("    </tr>");
		pBufferedWriter.newLine();
	}

	/**
	 * Get the weeks number from the sheet.
	 * 
	 * @param pSheet
	 *            Sheet to inspect.
	 * @return List of week numbers.
	 */
	public List<String> getSemaines(Sheet pSheet) {
		List<String> lSemaines = new LinkedList<String>();
		Cell lFirstCell = pSheet.findCell("SEMAINE");
		if (lFirstCell != null) {
			for (Cell lCell : pSheet.getColumn(lFirstCell.getColumn())) {
				String lNumeroSemaine = lCell.getContents();
				if ((!StringUtils.isEmpty(lNumeroSemaine))
						&& (!lNumeroSemaine.equals("SEMAINE"))) {
					lSemaines.add(lNumeroSemaine);
				}
			}
		}
		return lSemaines;
	}

	private List<Integer> getSemainesRowNumber(Sheet pSheet) {
		List<Integer> lSemaines = new LinkedList<Integer>();
		Cell lFirstCell = pSheet.findCell("SEMAINE");
		if (lFirstCell != null) {
			for (Cell lCell : pSheet.getColumn(lFirstCell.getColumn())) {
				String lNumeroSemaine = lCell.getContents();
				if ((!StringUtils.isEmpty(lNumeroSemaine))
						&& (!lNumeroSemaine.equals("SEMAINE"))
						&& (lCell.getRow() > lFirstCell.getRow())) {
					lSemaines.add(lCell.getRow());
				}
			}
		}
		return lSemaines;
	}

	public Writer getWriter() {
		return writer;
	}

	public void setWriter(Writer writer) {
		this.writer = writer;
	}
}
